package com.bc.mcode.core;

import com.bc.mcode.collect.Lists;
import com.bc.mcode.collect.Maps;
import com.bc.mcode.model.ClockVO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 闹钟主对象
 */
public class ClockManager {

    protected Logger log = LogManager.getLogger(getClass().getName());

    //60个时刻某个时刻挂的数据较多，60*60某个时刻挂的数据少，这里是根据一分一秒挂一个数据 如果是按天的 可以 24*60*60
    private  int clocknum = 60*60;

    //单例模式对象
    public static ClockManager manager = new ClockManager();

    //需要提醒的数据
    private Map<Integer, List<ClockVO>> clockMap = Collections.synchronizedMap(Maps.newHashMap());

    /**
     * 构造函数中创建时间
     */
    private ClockManager() {
        for (int i=0 ; i<clocknum; i++ ){
            List<ClockVO> list = Lists.newArrayList();
            clockMap.put(i,list);
        }
    }

    /**
     * 单例模式，使用一个闹钟对象
     * @return
     */
    public static ClockManager getInstance(){
        return manager;
    }

    /**
     * 根据参数时间 获取 时间key
     * @param c1
     * @return
     */
    public int getKey(Calendar c1){
        int m = c1.get(Calendar.MINUTE);
        int s = c1.get(Calendar.SECOND);
        int key = m*60+s;
        return key;
    }

    /**
     * 时间转换成Date
     * @param str
     * @return
     */
    public Date getDate(String str)  {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = simpleDateFormat.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 在某一时刻增加数据
     * @param clockVO
     */
    public void addClockVO(ClockVO clockVO){
        Date date = getDate(clockVO.getClockTime());
        Calendar c1 = Calendar.getInstance();
        c1.setTime(date);
        int key = getKey(c1);
        if(key < 0 || key > 60*60){
            log.error("add clockVO false, id must be 0~60*60.");
            return ;
        }
        clockMap.get(key).add(clockVO);
        log.info("add-data key:" + key);
    }

    /**
     * 计算当前时间是不是需要数据提醒
     * @param
     */
    public void taskMain(){
        Calendar c1 = Calendar.getInstance();
        int key = getKey(c1);
        if(key%100 == 0){
            log.info("ClockManager taskMain  key : " + key);
        }
        List<ClockVO> list  = clockMap.get(key);
        long time = c1.getTimeInMillis();
        if(list.size() > 0){
            List<ClockVO> rmList = Lists.newArrayList();
            for (int i = 0; i < list.size(); i++){
                ClockVO cloclVO = list.get(i);
                long cTime = getDate(cloclVO.getClockTime()).getTime();
                //如果时间到了，执行响应方法 失败时插入队列
                if(time >= cTime){
                    ClockResponse.getInstance().responseFrist(cloclVO);
                    //这个数据算完就过去了 相当于移交给 ClockResponse 处理 1.发送成功修改状态 2.发送失败继续发送
//                    clockMap.get(key).remove(cloclVO);
                    rmList.add(cloclVO);
                }
            }
            clockMap.get(key).removeAll(rmList);
        }
    }

    /**
     * 启动时钟转盘 计算队列
     */
//    public void start(){
//        Timer timer = new Timer();
//        log.info("ClockManager Core start ...");
//        timer.scheduleAtFixedRate(new TimerTask() {
//            public void run() {
//                taskMain();
//            }
//        }, 1000, 1000);
//    }


    /**
     * 启动时钟转盘 计算队列 - V2 code by cuimiao
     */
    public void start(){
//        Timer timer = new Timer();
//        log.info("ClockManager Core start ...");
//        timer.scheduleAtFixedRate(new TimerTask() {
//            public void run() {
//                taskMain();
//            }
//        }, 1000, 1000);
        log.info("继续发送队列 ClockManager Core start V2...");
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(30);
        pool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                taskMain();
            }
        }, 1000, 1000, TimeUnit.MILLISECONDS);
    }

    /**
     * 获取时间轮盘上的数据长度
     * @return
     */
    public int getDataNum(){
        int num = 0;
        Set<Integer>  set = clockMap.keySet();
        Iterator<Integer> iter = set.iterator();
        while (iter.hasNext()){
            int key = iter.next();
            List<ClockVO> list  =  clockMap.get(key);
            num = list.size()+num;
        }
        return num;
    }

    /**
     * 获取时间轮盘上的数据
     * @return
     */
    public Map<Integer, List<ClockVO>> getData(){
        return clockMap;
    }

    /**
     * 删除时间轮盘数据
     * @param id
     * @param time
     */
    public void deleClockVO(int id ,String time){
        Date date = getDate(time);
        Calendar c1 = Calendar.getInstance();
        c1.setTime(date);
        int key = getKey(c1);
        List<ClockVO> list  =  clockMap.get(key);
        int index = -1;
        for(int i=0; i< list.size(); i++){
            if(id==list.get(i).getClockId()){
                index = i;
                break;
            }
        }
        if(index != -1){
            clockMap.get(key).remove(index);
        }
    }



}
